/* eslint-disable camelcase */
export function adaptive(max, min) {
  let self_realLower = 0.0;
  let self_realUpper = 0.0;
  let self_lower = max;
  let self_upper = min;
  let self_nDiv = 5;
  let self_nMin = 1;
  let self_shrink = 0.75;
  let self_h = 1.5;
  let self_h5 = 2.75;
  let self_eps = 1.0e-7;
  let self_unit = 0.1;
  let self_force_nDiv = true;

  let dbl_min = 2.2250738585072014e-308;
  let dbl_max = 1.7976931348623157e308;
  let dbl_epsilon = 2.22044604925031e-16;
  let cell = 0;
  let i_small = false;
  let base = 0;
  let unit = 0;
  let ns = 0;
  let nu = 0;
  let k = 0;
  let internals = 0;
  if (self_lower > self_upper) {
    self_realUpper = self_lower;
    self_realLower = self_upper;
  } else {
    self_realUpper = self_upper;
    self_realLower = self_lower;
  }
  let dx = self_realUpper - self_realLower;
  if ((dx === 0) && (self_realUpper === 0)) {
    cell = 1.0;
    i_small = true;
  } else {
    cell = Math.max(Math.abs(self_realUpper), Math.abs(self_realLower));
    if (self_h5 >= (1.5 * self_h + 0.5)) {
      unit = 1.0 + 1 / (1 + self_h);
    } else {
      unit = 1.0 + 1.5 / (1.0 + self_h5);
      i_small = dx < cell * unit * max(1.0, self_nDiv) * dbl_epsilon * 3;
    }
  }
  if (i_small) {
    if (cell > 10) {
      cell = 9.0 + cell / 10.0;
      cell *= self_shrink;
    }
    if (self_nMin > 1) {
      cell /= self_nMin;
    }
  } else {
    cell = dx;
    if (self_nDiv > 1) {
      cell /= self_nDiv;
    }
  }
  if (cell < 20 * dbl_min) {
    cell = 20 * dbl_min;
  }
  if (10 * cell > dbl_max) {
    cell = 0.1 * dbl_max;
  }
  base = Math.pow(10.0, Math.floor(Math.log10(cell)));
  self_unit = base;
  unit = 2 * base;
  if (unit - cell < self_h * (cell - self_unit)) {
    self_unit = unit;
    unit = 5 * base;
    if (unit - cell < self_h5 * (cell - self_unit)) {
      self_unit = unit;
      unit = 10 * base;
      if (unit - cell < self_h * (cell - self_unit)) {
        self_unit = unit;
      }
    }
  }
  ns = Math.floor(self_realLower / self_unit + dbl_epsilon);
  nu = Math.ceil(self_realUpper / self_unit - dbl_epsilon);
  if (self_eps !== 0 && (self_eps > 1 || !i_small)) {
    if (self_realLower !== 0) {
      self_realLower *= (1 - dbl_epsilon);
    } else {
      self_realLower = -dbl_min;
    }
    if (self_realUpper !== 0) {
      self_realUpper *= (1 + dbl_epsilon);
    } else {
      self_realUpper = dbl_min;
    }
  }
  while ((ns * self_unit) > (self_realLower + dbl_epsilon * self_unit)) {
    ns -= 1;
  }
  while ((nu * self_unit) < (self_realUpper - dbl_epsilon * self_unit)) {
    nu += 1;
  }
  k = nu - ns + 0.5;
  if (k < self_nMin) {
    k = self_nMin - k;
    let temp = parseInt(k);
    if (ns >= 0.0) {
      nu += Math.ceil(k / 2);
      ns -= Math.floor(k / 2) + temp % 2;
    } else {
      ns -= Math.floor(k / 2);
      nu += Math.ceil(k / 2) + temp % 2;
    }
  } else {
    if (!self_force_nDiv) {
      self_nDiv = parseInt(k);
    }
  }
  if (ns * self_unit < self_realLower) {
    self_realLower = ns * self_unit;
  }
  if (nu * self_unit > self_realUpper) {
    self_realUpper = nu * self_unit;
  }
  internals = parseInt((self_realUpper - self_realLower) / self_unit + 0.5);
  if (self_force_nDiv && internals !== self_nDiv) {
    let step;
    if (internals > self_nDiv) {
      step = base;
    } else {
      step = -base;
    }
    unit = self_unit;
    let size = Math.abs(internals - self_nDiv);
    let nDiv;
    for (let i = 0; i < size + 1; i++) {
      unit += step;
      nDiv = parseInt((self_realUpper - self_realLower) / unit + 0.5);
      if (internals > self_nDiv) {
        if (nDiv <= self_nDiv) {
          self_unit = unit;
          break;
        }
      } else {
        if (nDiv >= self_nDiv) {
          self_unit = unit;
          break;
        }
      }
    }
  }
  // console.log(max, min, self_realUpper, self_realLower, self_unit);
  return {
    max: self_realUpper,
    min: self_realLower,
    interval: self_unit,
  };
}
